x86: Clean up vcpu initialisation (especially xsave save area)
authorKeir Fraser <keir@xen.org>
Tue, 16 Nov 2010 14:09:13 +0000 (14:09 +0000)
committerKeir Fraser <keir@xen.org>
Tue, 16 Nov 2010 14:09:13 +0000 (14:09 +0000)
Signed-off-by: Keir Fraser <keir@xen.org>
xen/arch/x86/domain.c
xen/arch/x86/i387.c
xen/include/asm-x86/i387.h

index 87439f8de9e21cd31044b73fb9d53d37d6bbd58b..6cdb6d85c66d97912774052ac1c6e5703efe9b74 100644 (file)
@@ -343,60 +343,44 @@ int vcpu_initialise(struct vcpu *v)
 
     paging_vcpu_init(v);
 
-    if ( cpu_has_xsave )
-    {
-        /* XSAVE/XRSTOR requires the save area be 64-byte-boundary aligned. */
-        void *xsave_area = _xmalloc(xsave_cntxt_size, 64);
-        if ( xsave_area == NULL )
-            return -ENOMEM;
-
-        xsave_init_save_area(xsave_area);
-        v->arch.xsave_area = xsave_area;
-        v->arch.xcr0 = XSTATE_FP_SSE;
-        v->arch.xcr0_accum = XSTATE_FP_SSE;
-    }
+    v->arch.perdomain_ptes = perdomain_ptes(d, v);
+
+    spin_lock_init(&v->arch.shadow_ldt_lock);
+
+    if ( (rc = xsave_alloc_save_area(v)) != 0 )
+        return rc;
 
     if ( is_hvm_domain(d) )
     {
         if ( (rc = hvm_vcpu_initialise(v)) != 0 )
-        {
-            xfree(v->arch.xsave_area);
-            return rc;
-        }
+            xsave_free_save_area(v);
+        return rc;
     }
-    else
-    {
-        /* PV guests by default have a 100Hz ticker. */
-        if ( !is_idle_domain(d) )
-            v->periodic_period = MILLISECS(10);
 
-        /* PV guests get an emulated PIT too for video BIOSes to use. */
-        if ( !is_idle_domain(d) && (v->vcpu_id == 0) )
-            pit_init(v, cpu_khz);
+    /* PV guests by default have a 100Hz ticker. */
+    if ( !is_idle_domain(d) )
+        v->periodic_period = MILLISECS(10);
 
-        v->arch.schedule_tail = continue_nonidle_domain;
-        v->arch.ctxt_switch_from = paravirt_ctxt_switch_from;
-        v->arch.ctxt_switch_to   = paravirt_ctxt_switch_to;
+    /* PV guests get an emulated PIT too for video BIOSes to use. */
+    if ( !is_idle_domain(d) && (v->vcpu_id == 0) )
+        pit_init(v, cpu_khz);
 
-        if ( is_idle_domain(d) )
-        {
-            v->arch.schedule_tail = continue_idle_domain;
-            v->arch.cr3           = __pa(idle_pg_table);
-        }
+    v->arch.schedule_tail = continue_nonidle_domain;
+    v->arch.ctxt_switch_from = paravirt_ctxt_switch_from;
+    v->arch.ctxt_switch_to   = paravirt_ctxt_switch_to;
 
-        v->arch.guest_context.ctrlreg[4] =
-            real_cr4_to_pv_guest_cr4(mmu_cr4_features);
+    if ( is_idle_domain(d) )
+    {
+        v->arch.schedule_tail = continue_idle_domain;
+        v->arch.cr3           = __pa(idle_pg_table);
     }
 
-    v->arch.perdomain_ptes = perdomain_ptes(d, v);
-
-    spin_lock_init(&v->arch.shadow_ldt_lock);
+    v->arch.guest_context.ctrlreg[4] =
+        real_cr4_to_pv_guest_cr4(mmu_cr4_features);
 
-    rc = 0;
-    if ( is_pv_32on64_vcpu(v) )
-        rc = setup_compat_l4(v);
+    rc = is_pv_32on64_vcpu(v) ? setup_compat_l4(v) : 0;
     if ( rc )
-        xfree(v->arch.xsave_area);
+        xsave_free_save_area(v);
 
     return rc;
 }
@@ -406,7 +390,7 @@ void vcpu_destroy(struct vcpu *v)
     if ( is_pv_32on64_vcpu(v) )
         release_compat_l4(v);
 
-    xfree(v->arch.xsave_area);
+    xsave_free_save_area(v);
 
     if ( is_hvm_vcpu(v) )
         hvm_vcpu_destroy(v);
index 1398b8fa5bf7e1343d2e60b7205eb69f0a65b054..82dd88e92009554228e3889ecf69e74a1182bc63 100644 (file)
@@ -204,12 +204,33 @@ void xsave_init(void)
     }
 }
 
-void xsave_init_save_area(void *save_area)
+int xsave_alloc_save_area(struct vcpu *v)
 {
-    memset(save_area, 0, xsave_cntxt_size);
+    void *save_area;
+
+    if ( !cpu_has_xsave )
+        return 0;
+
+    /* XSAVE/XRSTOR requires the save area be 64-byte-boundary aligned. */
+    save_area = _xmalloc(xsave_cntxt_size, 64);
+    if ( save_area == NULL )
+        return -ENOMEM;
 
+    memset(save_area, 0, xsave_cntxt_size);
     ((u32 *)save_area)[6] = 0x1f80;  /* MXCSR */
     *(uint64_t *)(save_area + 512) = XSTATE_FP_SSE;  /* XSETBV */
+
+    v->arch.xsave_area = save_area;
+    v->arch.xcr0 = XSTATE_FP_SSE;
+    v->arch.xcr0_accum = XSTATE_FP_SSE;
+
+    return 0;
+}
+
+void xsave_free_save_area(struct vcpu *v)
+{
+    xfree(v->arch.xsave_area);
+    v->arch.xsave_area = NULL;
 }
 
 /*
index ba773e99edc9baa150bf5415f2156fd37072bbf5..0e01d1604d49d3a793a35adb32762334059e85f7 100644 (file)
@@ -17,8 +17,9 @@
 extern unsigned int xsave_cntxt_size;
 extern u64 xfeature_mask;
 
-extern void xsave_init(void);
-extern void xsave_init_save_area(void *save_area);
+void xsave_init(void);
+int xsave_alloc_save_area(struct vcpu *v);
+void xsave_free_save_area(struct vcpu *v);
 
 #define XSTATE_FP       (1 << 0)
 #define XSTATE_SSE      (1 << 1)